home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PCMania 43
/
PCMania CD43_1.nrg
/
midi
/
midi2txt.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1995-06-05
|
15KB
|
764 lines
#include "midiio.hpp"
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <dos.h>
// info = -1 is lyric!
class MidiPrint : public MidiRead
{
public:
MidiPrint(char* name);
virtual void head(unsigned songs, unsigned tracks, unsigned clicksperquarter);
virtual void track(int trackno, unsigned length, int channel);
virtual void endtrack(int trackno);
virtual void seqnumber(unsigned int seqno);
virtual void text(int what, int len, char* whattext, unsigned char* txt);
virtual void meta(int what, int len, unsigned char* data);
virtual void end();
virtual void smpteofs(int hour, int min, int sec, int frame, int fracframe);
virtual void tact(int nom, int denom, int clicksperbeat, int notes32perbeat);
virtual void tempo(unsigned long ticks);
virtual void key(int signature, int isminor);
virtual void program(int prg, int channel);
virtual void control(int channel, int what, int value);
virtual void highbank(int channel, int val);
virtual void wheel(int channel, int val);
virtual void breath(int channel, int val);
virtual void foot(int channel, int val);
virtual void portamentotime(int channel, int val);
virtual void data(int channel, int val);
virtual void volume(int channel, int val);
virtual void balance(int channel, int val);
virtual void expression(int channel, int val);
virtual void lowbank(int channel, int val);
virtual void hold(int channel, int val);
virtual void reverb(int channel, int val);
virtual void chorus(int channel, int val);
virtual void datainc(int channel, int val);
virtual void datadec(int channel, int val);
virtual void noteon(int channel, int note, int vel);
virtual void noteoff(int channel, int note, int vel);
virtual void time(unsigned long ticks);
virtual void pitchbend(int channel, int val);
virtual void polyaftertouch(int channel, int note, int val);
virtual void aftertouch(int channel, int val);
virtual void songpos(unsigned pos);
virtual void songselect(unsigned char song);
virtual void tunerequest();
virtual void timingclock();
virtual void start();
virtual void cont();
virtual void stop();
virtual void activesense();
virtual void sysex(int syslen, unsigned char* sysdata);
virtual void endmidi();
virtual void error(const char* msg);
virtual void percent(int perc);
void printchannel(int channel);
int info_;
int marktact_;
private:
int indent_;
unsigned tactunits_;
unsigned quarterunits_;
unsigned long curtime_;
int nl_;
void indent();
};
MidiPrint::MidiPrint(char* name) : MidiRead(name)
{
indent_ = 0;
info_ = 3;
marktact_ = 0;
tactunits_ = 0;
nl_ = 1;
}
void MidiPrint::indent()
{
for (; indent_ > 0; indent_--)
putchar(' ');
}
void MidiPrint::head(unsigned songs, unsigned tracks, unsigned clicksperquarter)
{
quarterunits_ = clicksperquarter;
if (midiname_)
printf("// %s\n", midiname_);
if (info_ == 1 || info_ == -1)
return;
printf("mthd\n");
printf(" // %d song%s\n", songs, songs != 1 ? "s" : "");
printf(" // %d track%s\n", tracks, tracks != 1 ? "s" : "");
printf(" unit %d // is 1/4\n", clicksperquarter);
printf("end mthd\n");
}
void MidiPrint::track(int trackno, unsigned length, int channel)
{
curtime_ = 0;
if (info_ == 1 || info_ == -1)
return;
printf("\nmtrk");
if (channel >= 0)
printf("($%X)\n", channel+1);
else if (channel == MULTICHANNEL)
printf(" // multichannel track\n");
else
printf("\n");
}
void MidiPrint::endtrack(int trackno)
{
if (info_ == 1)
return;
if (info_ == -1)
{
if (!nl_)
{
nl_ = 1;
printf("\n");
}
return;
}
printf("end mtrk\n");
}
void printchar(int c)
{
if (c < 0)
return;
if (c == '\\')
printf("\\\\");
else if (c == '"')
printf("\\\"");
else if (c != 0 && (isprint(c) || strchr("äöüÄÖÜß", c) != 0))
putchar(c);
else
printf("\\x%02x", c);
}
void MidiPrint::seqnumber(unsigned int seqno)
{
indent();
printf("seqnumber %u\n", seqno);
}
void MidiPrint::text(int what, int len, char* whattext, unsigned char* txt)
{
if (info_ == -1 && txt)
{
if (what == meta_lyric || what == meta_text)
{
char* bs;
while ((bs = (char*)memchr(txt, '\\', len)) != 0)
*bs = '\n';
while ((bs = (char*)memchr(txt, '/', len)) != 0)
*bs = '\n';
if (*txt == '@')
{
txt++; len--;
switch(*txt)
{
case 'K': printf("\nKind: "); break;
case 'V': printf("\nVersion: "); break;
case 'I': printf("\nInformation: "); break;
case 'T': printf("\nTitle: "); break;
case 'L': printf("\nLanguage: "); break;
default: printf("\n@%c: ", *txt); break;
}
if (*txt)
{
txt++;
len--;
}
}
nl_ = txt[len-1] == '\n';
printf("%.*s", len, txt);
}
return;
}
indent();
if (whattext)
printf("%s ", whattext);
else
printf("metaevent %d(%d) ", what, len);
putchar('"');
if (txt)
{
while (len-- > 0)
printchar(*txt++);
}
putchar('"');
if (!whattext)
printf(" end metaevent");
printf("\n");
}
void MidiPrint::meta(int what, int len, unsigned char* data)
{
int i;
if (info_ < 3)
return;
indent();
printf("metaevent %d(%d)", what, len);
i = 0;
while (len-- > 0)
{
indent_ = 4;
printf(" $%02X", *data++);
if ( (i % 16) == 15)
{
printf("\n");
indent();
}
i++;
}
printf(" end metaevent\n");
}
void MidiPrint::end()
{
}
void MidiPrint::smpteofs(int hour, int min, int sec, int frame, int fracframe)
{
if (info_ < 3)
return;
printf("smpteofs %02d:%02d:%02d:%d:%d\n",
hour, min, sec, frame, fracframe);
}
void MidiPrint::tact(int nom, int denom, int clicksperbeat, int notes32perbeat)
{
if (info_ < 1)
return;
indent();
printf("tact %d / %d %d %d\n", nom, denom, clicksperbeat, notes32perbeat);
if (!marktact_)
return;
if (tactunits_)
{
tactunits_ = 0;
marktact_ = 0;
}
else
tactunits_ = quarterunits_ * 4 * nom / denom;
}
void MidiPrint::tempo(unsigned long ticks)
{
if (info_ < 1)
return;
indent();
if (ticks != 0)
{
unsigned long beat = 60000000l / ticks;
if (beat * ticks == 60000000l)
{
printf("beats %ld\n", beat);
return;
}
}
printf("tempo %ld", ticks);
if (ticks != 0)
printf(" // about %ld beats/min", 60000000l / ticks);
printf("\n");
}
void MidiPrint::key(int signature, int isminor)
{
if (info_ < 3)
return;
indent();
printf("key \"");
if (signature != 0)
{
printf("%d%c ", (signature < 0) ? -signature : signature,
(signature < 0) ? 'b' : '#');
}
else
printf("C");
printf("%s\"\n", isminor ? "min" : "maj");
}
void MidiPrint::printchannel(int channel)
{
if (info_ < 3)
return;
if (getchannel() != channel)
{
indent();
if (channel >= 10)
printf("[$%X]", channel+1);
else if (channel >= 0)
printf("[%d]", channel+1);
setchannel(channel);
}
}
void MidiPrint::time(unsigned long ticks)
{
unsigned long n;
indent_ = 2;
while (ticks > 0)
{
if (!marktact_ || !tactunits_)
n = ticks;
else
{
if (curtime_ % tactunits_ == 0)
n = tactunits_;
else
n = tactunits_ - curtime_ % tactunits_;
if (n > ticks)
n = ticks;
}
if (info_ < 3)
return;
if (n > 0)
{
indent();
curtime_ += n;
if ((n % quarterunits_) == 0)
printf("%d/4", n / quarterunits_);
else if (quarterunits_ % 2 == 0 && (n % (quarterunits_ / 2)) == 0)
printf("%d/8", n / (quarterunits_/2));
else if (quarterunits_ % 4 == 0 && (n % (quarterunits_ / 4)) == 0)
printf("%d/16", n / (quarterunits_/4));
else
printf("%ld", n);
if (!marktact_ || !tactunits_ || (curtime_ % tactunits_) != 0)
putchar(';');
else
{
printf(". // tact %lu\n", curtime_ / tactunits_);
indent_ = 2;
}
ticks -= n;
}
}
}
void MidiPrint::program(int channel, int prg)
{
if (info_ < 1)
return;
indent();
printchannel(channel);
printf("program %s\n", progname(prg, channel));
}
void MidiPrint::control(int channel, int what, int value)
{
if (info_ < 3)
return;
indent();
printchannel(channel);
printf("control $%02X %d\n", what, value);
}
void MidiPrint::balance(int channel, int val)
{
if (info_ < 3)
return;
indent();
printchannel(channel);
printf("balance ");
if (val == 0)
printf(" left\n");
else if (val == 127)
printf(" right\n");
else
printf(" %d\n", val);
}
void MidiPrint::highbank(int channel, int val)
{
if (info_ < 2)
return;
indent();
printchannel(channel);
printf("hbank $%02X\n", val);
}
void MidiPrint::wheel(int channel, int val)
{
if (info_ < 3)
return;
indent();
printchannel(channel);
printf("wheel %d\n", val);
}
void MidiPrint::breath(int channel, int val)
{
if (info_ < 3)
return;
indent();
printchannel(channel);
printf("breath %d\n", val);
}
void MidiPrint::foot(int channel, int val)
{
if (info_ < 3)
return;
indent();
printchannel(channel);
printf("foot %d\n", val);
}
void MidiPrint::portamentotime(int channel, int val)
{
if (info_ < 3)
return;
indent();
printchannel(channel);
printf("portamentotime %d\n", val);
}
void MidiPrint::data(int channel, int val)
{
if (info_ < 3)
return;
indent();
printchannel(channel);
printf("data %d\n", val);
}
void MidiPrint::volume(int channel, int val)
{
if (info_ < 2)
return;
indent();
printchannel(channel);
printf("volume %d\n", val);
}
void MidiPrint::expression(int channel, int val)
{
if (info_ < 3)
return;
indent();
printchannel(channel);
printf("expression %d\n", val);
}
void MidiPrint::lowbank(int channel, int val)
{
if (info_ < 2)
return;
indent();
printchannel(channel);
printf("lbank $%02X\n", val);
}
void MidiPrint::hold(int channel, int val)
{
if (info_ < 3)
return;
indent();
printchannel(channel);
printf("hold ");
if (val == 0)
printf(" off\n");
else if (val == 0x7f)
printf(" on\n");
else
printf(" %d\n", val);
}
void MidiPrint::reverb(int channel, int val)
{
if (info_ < 3)
return;
indent();
printchannel(channel);
printf("reverb %d\n", val);
}
void MidiPrint::chorus(int channel, int val)
{
if (info_ < 3)
return;
indent();
printchannel(channel);
printf("chorus %d\n", val);
}
void MidiPrint::datainc(int channel, int val)
{
if (info_ < 3)
return;
indent();
printchannel(channel);
printf("datainc %d\n", val);
}
void MidiPrint::datadec(int channel, int val)
{
if (info_ < 3)
return;
indent();
printchannel(channel);
printf("datadec %d\n", val);
}
void MidiPrint::noteon(int channel, int note, int vel)
{
if (info_ < 3)
return;
indent();
printchannel(channel);
printf("+%s $%02X;\n", notename(note), vel);
}
void MidiPrint::noteoff(int channel, int note, int vel)
{
if (info_ < 3)
return;
indent();
printchannel(channel);
printf("-%s $%02X;\n", notename(note), vel);
}
void MidiPrint::pitchbend(int channel, int val)
{
if (info_ < 3)
return;
indent();
printchannel(channel);
printf("pitchbend %d\n", val);
}
void MidiPrint::polyaftertouch(int channel, int note, int val)
{
if (info_ < 3)
return;
indent();
printchannel(channel);
printf("polyaftertouch %s %d\n", notename(note), val);
}
void MidiPrint::aftertouch(int channel, int val)
{
if (info_ < 3)
return;
indent();
printchannel(channel);
printf("aftertouch %d\n", val);
}
void MidiPrint::songpos(unsigned pos)
{
if (info_ < 1)
return;
indent();
printf("songpos %d\n", pos);
}
void MidiPrint::songselect(unsigned char song)
{
if (info_ < 1)
return;
indent();
printf("songselect %d\n", song);
}
void MidiPrint::tunerequest()
{
if (info_ < 3)
return;
indent();
printf("tunerequest\n");
}
void MidiPrint::timingclock()
{
if (info_ < 3)
return;
indent();
printf("timingclock\n");
}
void MidiPrint::start()
{
if (info_ < 1)
return;
indent();
printf("start\n");
}
void MidiPrint::cont()
{
if (info_ < 1)
return;
indent();
printf("continue\n");
}
void MidiPrint::stop()
{
if (info_ < 1)
return;
indent();
printf("stop\n");
}
void MidiPrint::activesense()
{
if (info_ < 3)
return;
indent();
printf("activesensing\n");
}
void MidiPrint::sysex(int syslen, unsigned char* sysdata)
{
int i = 0;
if (info_ < 3)
return;
indent();
syslen--; // last byte is end of sysex (F7)
printf("sysevent(%d) ", syslen);
while (syslen-- > 0)
{
indent_ = 4;
printf("$%02X ", *sysdata++);
if ( (i % 16) == 15)
{
printf("\n");
indent();
}
i++;
}
printf("end sysevent\n");
}
void MidiPrint::endmidi()
{
if (info_ < 3)
return;
if (getpos() < filesize_)
{
long len = filesize_ - getpos();
fprintf(stderr, "garbage at end of midi\n");
while (len > 0)
{
int n = 16;
if (len < n)
n = (int)len;
unsigned char* c = get(n);
if (!c)
return;
printf("//");
for (int i = 0; i < n; i++)
printf(" %02X", c[i]);
printf("\n");
len -= n;
}
}
}
void MidiPrint::percent(int perc)
{
if (info_ >= 0)
fprintf(stderr, "%-3d%%\r", perc);
}
void MidiPrint::error(const char* msg)
{
printf("// error: %s\n", msg);
}
void usage()
{
fprintf(stderr, "usage: midi2txt [-chunk][-short][-info][-lyric][-tact] file.mid [> file.txt]\n");
exit(1);
}
void main(int argc, char**argv)
{
int info = 3;
int tact = 0;
setcbrk(1);
argc--; argv++;
while (argc > 0 && **argv == '-')
{
if (argc > 0 && strnicmp(*argv, "-chunk", 2) == 0)
{
info = 0;
argc--; argv++;
continue;
}
if (argc > 0 && strnicmp(*argv, "-short", 2) == 0)
{
info = 1;
argc--; argv++;
continue;
}
if (argc > 0 && strnicmp(*argv, "-info", 2) == 0)
{
info = 2;
argc--; argv++;
continue;
}
if (argc > 0 && strnicmp(*argv, "-lyric", 2) == 0)
{
info = -1;
argc--; argv++;
continue;
}
if (argc > 0 && strnicmp(*argv, "-tact", 2) == 0)
{
tact = 1;
argc--; argv++;
continue;
}
fprintf(stderr, "invalid option %s\n", *argv);
argc--; argv++;
usage();
}
if (argc == 0)
usage();
MidiPrint midi(*argv);
if (errno != 0)
{
perror(*argv);
return;
}
fprintf(stderr, "%s\n", *argv);
midi.info_ = info;
midi.marktact_ = tact;
if (info == 0)
midi.options_ = OPTION_NOEVENTS;
if (!midi.run())
fprintf(stderr, "midi error at %lx\n", midi.getpos());
}